﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TotalLMS.Util;
using System.Reflection;
using System.Security;
using System.Runtime.Serialization;

namespace TotalLMS.Datamodels.cmi
{
    /// <summary>
    /// File Description:   This class represents a CMI Category.  This class
    /// acts as a parent to all of the CMI Data Element
    ///     Categories:
    ///     CMICore, CMIScore, CMISuspendData, CMILaunchData,
    ///     CMIComments, CMIObjectives, CMIObjectiveData,
    ///     CMIEvaluation, CMIEvaluation, CMIEvaluationData,
    ///     CMIInteractions, CMIInteractionData, CMIResponse,
    ///     CMIStudentData, CMIEvaluationComments, CMIAttempt,
    ///     CMITries, CMIStudentDemographics, CMIPath
    ///     and CMIStudentPreference
    /// </summary>
    public class CMICategory:ISerializable
    {
        // Indicates whether or not the category can be set by an AU
        protected bool writeable;

        /// <summary>
        /// Input: boolean writeableFlag
        /// Output: none        
        /// Description:  Constructs a Data Model Category        
        /// </summary>
        /// <param name="writeableFlag"></param>
        public CMICategory(bool writeableFlag)
        {
            writeable = writeableFlag;
        }  // end of constructor


        public bool isWriteable()
        {
            return writeable;
        }  // end of isWriteable()

        public String determineElementValue(Object o, String element, DMErrorManager dmErrorMgr)
        {
            // Value to return
            String rtrnString = String.Empty;

            // Get the Class name off of the Object
            
            //Class c = o.getClass();
            Type t = o.GetType();

            try
            {
                // Use reflection to obtain the appropriate field (attribute)
                // Get the Field (in Class c) that matches the element

                //Field tmpField = c.getField(element);
                
                FieldInfo tmpField = t.GetField(element);
                //TODO: translate this V.S 21-Feb-2012
                //==================================================
                // Get the Element object that is represented by the Field
                //Element e = (Element)tmpField.get(o);
                //object e = tmpField.GetValue(o);

                //if (e.isReadable())                
                {
                    // get the value off of the Element
                    //rtrnString = e.getValue();
                }
                //else
                //{
                //V.S 21-Feb-2012==================================================
                
                    if (DebugIndicator.ON)
                    {
                        Console.WriteLine("Error - Element not readable");
                        Console.WriteLine("Value: " + element + " is not readable");
                    }

                    // Notify error manager
                    dmErrorMgr.SetCurrentErrorCode("404");
                //}
                //V.S 21-Feb-2012==================================================
                
            }
            //catch ( NoSuchFieldException nsfe )
            catch (FieldAccessException fae)
            {
                if (element.Equals("_count") == true)
                {
                    if (DebugIndicator.ON)
                    {
                        Console.WriteLine("Error - Element not an array");
                        Console.WriteLine("Element Cannont have count");
                    }
                    dmErrorMgr.SetCurrentErrorCode("203");
                }
                else
                {
                    if (DebugIndicator.ON)
                    {
                        Console.WriteLine("Error - Invalid Argument Error");
                        Console.WriteLine("Invalid data model element: " + element);
                    }

                    // Notify error manager
                    dmErrorMgr.SetCurrentErrorCode("201");
                }
            }
            catch (SecurityException se)
            {
                if (DebugIndicator.ON)
                {
                    Console.WriteLine(se);
                    Console.WriteLine("Access to the information is denied");
                }

                // Notify error manager
                dmErrorMgr.SetCurrentErrorCode("101");
            }
            //catch ( IllegalAccessException iae )
            catch (MethodAccessException mae)
            {
                if (DebugIndicator.ON)
                {
                    Console.WriteLine(mae);
                    Console.WriteLine("Underlying constructor is inaccessible");
                }
                // Notify error manager
                dmErrorMgr.SetCurrentErrorCode("101");
            }

            return rtrnString;

        } // end of determineElementValue()




        #region ISerializable Members
        //TODO: how to implement this interface method
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
